home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / wave.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  25KB  |  1,045 lines

  1. /***************************************************************************
  2.  
  3.     wave.c
  4.  
  5.     Functions to handle loading, creation, recording and playback
  6.     of wave samples for IO_CASSETTE
  7.  
  8. ****************************************************************************/
  9. #include "driver.h"
  10.  
  11. /* from mame.c */
  12. extern int bitmap_dirty;
  13.  
  14. /* Our private wave file structure */
  15. struct wave_file {
  16.     int channel;            /* channel for playback */
  17.     void *file;             /* osd file handle */
  18.     int mode;                /* write mode? */
  19.     int (*fill_wave)(INT16 *,int,UINT8*);
  20.     void *timer;            /* timer (TIME_NEVER) for reading sample values */
  21.     INT16 play_sample;        /* current sample value for playback */
  22.     INT16 record_sample;    /* current sample value for playback */
  23.     int display;            /* display tape status on screen */
  24.     int offset;             /* offset set by device_seek function */
  25.     int playpos;            /* sample position for playback */
  26.     int counter;            /* sample fraction counter for playback */
  27.     int smpfreq;            /* sample frequency from the WAV header */
  28.     int resolution;         /* sample resolution in bits/sample (8 or 16) */
  29.     int samples;            /* number of samples (length * resolution / 8) */
  30.     int length;             /* length in bytes */
  31.     void *data;             /* sample data */
  32. };
  33.  
  34. static struct Wave_interface *intf;
  35. static struct wave_file wave[MAX_WAVE] = {{-1,},{-1,}};
  36.  
  37. #ifdef LSB_FIRST
  38. #define intelLong(x) (x)
  39. #else
  40. #define intelLong(x) (((x << 24) | (((unsigned long) x) >> 24) | \
  41.                        (( x & 0x0000ff00) << 8) | (( x & 0x00ff0000) >> 8)))
  42. #endif
  43.  
  44. #define WAVE_OK    0
  45. #define WAVE_ERR   1
  46. #define WAVE_FMT   2
  47.  
  48. /*****************************************************************************
  49.  * helper functions
  50.  *****************************************************************************/
  51. static int wave_read(int id)
  52. {
  53.     struct wave_file *w = &wave[id];
  54.     UINT32 offset = 0;
  55.     UINT32 filesize, temp32;
  56.     UINT16 channels, bits, temp16;
  57.     char buf[32];
  58.  
  59.     if( !w->file )
  60.         return WAVE_ERR;
  61.  
  62.     /* read the core header and make sure it's a WAVE file */
  63.     offset += osd_fread(w->file, buf, 4);
  64.     if( offset < 4 )
  65.     {
  66.         logerror("WAVE read error at offs %d\n", offset);
  67.         return WAVE_ERR;
  68.     }
  69.     if( memcmp (&buf[0], "RIFF", 4) != 0 )
  70.     {
  71.         logerror("WAVE header not 'RIFF'\n");
  72.         return WAVE_FMT;
  73.     }
  74.  
  75.     /* get the total size */
  76.     offset += osd_fread(w->file, &temp32, 4);
  77.     if( offset < 8 )
  78.     {
  79.         logerror("WAVE read error at offs %d\n", offset);
  80.         return WAVE_ERR;
  81.     }
  82.     filesize = intelLong(temp32);
  83.     logerror("WAVE filesize %u bytes\n", filesize);
  84.  
  85.     /* read the RIFF file type and make sure it's a WAVE file */
  86.     offset += osd_fread(w->file, buf, 4);
  87.     if( offset < 12 )
  88.     {
  89.         logerror("WAVE read error at offs %d\n", offset);
  90.         return WAVE_ERR;
  91.     }
  92.     if( memcmp (&buf[0], "WAVE", 4) != 0 )
  93.     {
  94.         logerror("WAVE RIFF type not 'WAVE'\n");
  95.         return WAVE_FMT;
  96.     }
  97.  
  98.     /* seek until we find a format tag */
  99.     while( 1 )
  100.     {
  101.         offset += osd_fread(w->file, buf, 4);
  102.         offset += osd_fread(w->file, &temp32, 4);
  103.         w->length = intelLong(temp32);
  104.         if( memcmp(&buf[0], "fmt ", 4) == 0 )
  105.             break;
  106.  
  107.         /* seek to the next block */
  108.         osd_fseek(w->file, w->length, SEEK_CUR);
  109.         offset += w->length;
  110.         if( offset >= filesize )
  111.         {
  112.             logerror("WAVE no 'fmt ' tag found\n");
  113.             return WAVE_ERR;
  114.         }
  115.     }
  116.  
  117.     /* read the format -- make sure it is PCM */
  118.     offset += osd_fread_lsbfirst(w->file, &temp16, 2);
  119.     if( temp16 != 1 )
  120.     {
  121.         logerror("WAVE format %d not supported (not = 1 PCM)\n", temp16);
  122.             return WAVE_ERR;
  123.     }
  124.     logerror("WAVE format %d (PCM)\n", temp16);
  125.  
  126.     /* number of channels -- only mono is supported */
  127.     offset += osd_fread_lsbfirst(w->file, &channels, 2);
  128.     if( channels != 1 && channels != 2 )
  129.     {
  130.         logerror("WAVE channels %d not supported (only 1 mono or 2 stereo)\n", channels);
  131.         return WAVE_ERR;
  132.     }
  133.     logerror("WAVE channels %d\n", channels);
  134.  
  135.     /* sample rate */
  136.     offset += osd_fread(w->file, &temp32, 4);
  137.     w->smpfreq = intelLong(temp32);
  138.     logerror("WAVE sample rate %d Hz\n", w->smpfreq);
  139.  
  140.     /* bytes/second and block alignment are ignored */
  141.     offset += osd_fread(w->file, buf, 6);
  142.  
  143.     /* bits/sample */
  144.     offset += osd_fread_lsbfirst(w->file, &bits, 2);
  145.     if( bits != 8 && bits != 16 )
  146.     {
  147.         logerror("WAVE %d bits/sample not supported (only 8/16)\n", bits);
  148.         return WAVE_ERR;
  149.     }
  150.     logerror("WAVE bits/sample %d\n", bits);
  151.     w->resolution = bits;
  152.  
  153.     /* seek past any extra data */
  154.     osd_fseek(w->file, w->length - 16, SEEK_CUR);
  155.     offset += w->length - 16;
  156.  
  157.     /* seek until we find a data tag */
  158.     while( 1 )
  159.     {
  160.         offset += osd_fread(w->file, buf, 4);
  161.         offset += osd_fread(w->file, &temp32, 4);
  162.         w->length = intelLong(temp32);
  163.         if( memcmp(&buf[0], "data", 4) == 0 )
  164.             break;
  165.  
  166.         /* seek to the next block */
  167.         osd_fseek(w->file, w->length, SEEK_CUR);
  168.         offset += w->length;
  169.         if( offset >= filesize )
  170.         {
  171.             logerror("WAVE not 'data' tag found\n");
  172.             return WAVE_ERR;
  173.         }
  174.     }
  175.  
  176.     /* allocate the game sample */
  177.     w->data = malloc(w->length);
  178.  
  179.     if( w->data == NULL )
  180.     {
  181.         logerror("WAVE failed to malloc %d bytes\n", w->length);
  182.         return WAVE_ERR;
  183.     }
  184.  
  185.     /* read the data in */
  186.     if( w->resolution == 8 )
  187.     {
  188.         if( osd_fread(w->file, w->data, w->length) != w->length )
  189.         {
  190.             logerror("WAVE failed read %d data bytes\n", w->length);
  191.             free(w->data);
  192.             return WAVE_ERR;
  193.         }
  194.         if( channels == 2 )
  195.         {
  196.             UINT8 *src = w->data;
  197.             INT8 *dst = w->data;
  198.             logerror("WAVE mixing 8-bit unsigned stereo to 8-bit signed mono\n");
  199.             /* convert stereo 8-bit data to mono signed samples */
  200.             for( temp32 = 0; temp32 < w->length/2; temp32++ )
  201.             {
  202.                 *dst = ((src[0] + src[1]) / 2) ^ 0x80;
  203.                 dst += 1;
  204.                 src += 2;
  205.             }
  206.             w->length /= 2;
  207.             w->data = realloc(w->data, w->length);
  208.             if( w->data == NULL )
  209.             {
  210.                 logerror("WAVE failed to malloc %d bytes\n", w->length);
  211.                 return WAVE_ERR;
  212.             }
  213.         }
  214.         else
  215.         {
  216.             UINT8 *src = w->data;
  217.             INT8 *dst = w->data;
  218.             logerror("WAVE converting 8-bit unsigned to 8-bit signed\n");
  219.             /* convert 8-bit data to signed samples */
  220.             for( temp32 = 0; temp32 < w->length; temp32++ )
  221.                 *dst++ = *src++ ^ 0x80;
  222.         }
  223.     }
  224.     else
  225.     {
  226.         /* 16-bit data is fine as-is */
  227.         if( osd_fread_lsbfirst(w->file, w->data, w->length) != w->length )
  228.         {
  229.             logerror("WAVE failed read %d data bytes\n", w->length);
  230.             free(w->data);
  231.             return WAVE_ERR;
  232.         }
  233.         if( channels == 2 )
  234.         {
  235.             INT16 *src = w->data;
  236.             INT16 *dst = w->data;
  237.             logerror("WAVE mixing 16-bit stereo to 16-bit mono\n");
  238.             /* convert stereo 16-bit data to mono */
  239.             for( temp32 = 0; temp32 < w->length/2; temp32++ )
  240.             {
  241.                 *dst = ((INT32)src[0] + (INT32)src[1]) / 2;
  242.                 dst += 1;
  243.                 src += 2;
  244.             }
  245.             w->length /= 2;
  246.             w->data = realloc(w->data, w->length);
  247.             if( w->data == NULL )
  248.             {
  249.                 logerror("WAVE failed to malloc %d bytes\n", w->length);
  250.                 return WAVE_ERR;
  251.             }
  252.         }
  253.         else
  254.         {
  255.             logerror("WAVE using 16-bit signed samples as is\n");
  256.         }
  257.     }
  258.     w->samples = w->length * 8 / w->resolution;
  259.     logerror("WAVE %d samples - %d:%02d\n", w->samples, (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60);
  260.  
  261.     return WAVE_OK;
  262. }
  263.  
  264. static int wave_write(int id)
  265. {
  266.     struct wave_file *w = &wave[id];
  267.     UINT32 filesize, offset = 0, temp32;
  268.     UINT16 temp16;
  269.  
  270.     if( !w->file )
  271.         return WAVE_ERR;
  272.  
  273.     while( w->playpos < w->samples )
  274.     {
  275.         *((INT16 *)w->data + w->playpos) = 0;
  276.         w->playpos++;
  277.     }
  278.  
  279.     filesize =
  280.         4 +     /* 'RIFF' */
  281.         4 +     /* size of entire file */
  282.         8 +     /* 'WAVEfmt ' */
  283.         20 +    /* WAVE tag  (including size -- 0x10 in dword) */
  284.         4 +     /* 'data' */
  285.         4 +     /* size of data */
  286.         w->length;
  287.  
  288.     /* write the core header for a WAVE file */
  289.     offset += osd_fwrite(w->file, "RIFF", 4);
  290.     if( offset < 4 )
  291.     {
  292.         logerror("WAVE write error at offs %d\n", offset);
  293.         return WAVE_ERR;
  294.     }
  295.  
  296.     temp32 = intelLong(filesize) - 8;
  297.     offset += osd_fwrite(w->file, &temp32, 4);
  298.  
  299.     /* read the RIFF file type and make sure it's a WAVE file */
  300.     offset += osd_fwrite(w->file, "WAVE", 4);
  301.     if( offset < 12 )
  302.     {
  303.         logerror("WAVE write error at offs %d\n", offset);
  304.         return WAVE_ERR;
  305.     }
  306.  
  307.     /* write a format tag */
  308.     offset += osd_fwrite(w->file, "fmt ", 4);
  309.     if( offset < 12 )
  310.     {
  311.         logerror("WAVE write error at offs %d\n", offset);
  312.         return WAVE_ERR;
  313.     }
  314.     /* size of the following 'fmt ' fields */
  315.     offset += osd_fwrite(w->file, "\x10\x00\x00\x00", 4);
  316.     if( offset < 16 )
  317.     {
  318.         logerror("WAVE write error at offs %d\n", offset);
  319.         return WAVE_ERR;
  320.     }
  321.  
  322.     /* format: PCM */
  323.     temp16 = 1;
  324.     offset += osd_fwrite_lsbfirst(w->file, &temp16, 2);
  325.     if( offset < 18 )
  326.     {
  327.         logerror("WAVE write error at offs %d\n", offset);
  328.         return WAVE_ERR;
  329.     }
  330.  
  331.     /* channels: 1 (mono) */
  332.     temp16 = 1;
  333.     offset += osd_fwrite_lsbfirst(w->file, &temp16, 2);
  334.     if( offset < 20 )
  335.     {
  336.         logerror("WAVE write error at offs %d\n", offset);
  337.         return WAVE_ERR;
  338.     }
  339.  
  340.     /* sample rate */
  341.     temp32 = intelLong(w->smpfreq);
  342.     offset += osd_fwrite(w->file, &temp32, 4);
  343.     if( offset < 24 )
  344.     {
  345.         logerror("WAVE write error at offs %d\n", offset);
  346.         return WAVE_ERR;
  347.     }
  348.  
  349.     /* byte rate */
  350.     temp32 = intelLong(w->smpfreq * w->resolution / 8);
  351.     offset += osd_fwrite(w->file, &temp32, 4);
  352.     if( offset < 28 )
  353.     {
  354.         logerror("WAVE write error at offs %d\n", offset);
  355.         return WAVE_ERR;
  356.     }
  357.  
  358.     /* block align (size of one `sample') */
  359.     temp16 = w->resolution / 8;
  360.     offset += osd_fwrite_lsbfirst(w->file, &temp16, 2);
  361.     if( offset < 30 )
  362.     {
  363.         logerror("WAVE write error at offs %d\n", offset);
  364.         return WAVE_ERR;
  365.     }
  366.  
  367.     /* block align */
  368.     temp16 = w->resolution;
  369.     offset += osd_fwrite_lsbfirst(w->file, &temp16, 2);
  370.     if( offset < 32 )
  371.     {
  372.         logerror("WAVE write error at offs %d\n", offset);
  373.         return WAVE_ERR;
  374.     }
  375.  
  376.     /* 'data' tag */
  377.     offset += osd_fwrite(w->file, "data", 4);
  378.     if( offset < 36 )
  379.     {
  380.         logerror("WAVE write error at offs %d\n", offset);
  381.         return WAVE_ERR;
  382.     }
  383.  
  384.     /* data size */
  385.     temp32 = intelLong(w->length);
  386.     offset += osd_fwrite(w->file, &temp32, 4);
  387.     if( offset < 40 )
  388.     {
  389.         logerror("WAVE write error at offs %d\n", offset);
  390.         return WAVE_ERR;
  391.     }
  392.  
  393.     if( osd_fwrite_lsbfirst(w->file, w->data, w->length) != w->length )
  394.     {
  395.         logerror("WAVE write error at offs %d\n", offset);
  396.         return WAVE_ERR;
  397.     }
  398.  
  399.     return WAVE_OK;
  400. }
  401.  
  402. static void wave_display(int id)
  403. {
  404.     static int tapepos = 0;
  405.     struct wave_file *w = &wave[id];
  406.  
  407.     if( abs(w->playpos - tapepos) > w->smpfreq / 4 )
  408.     {
  409.         char buf[32];
  410.         int x, y, n, t0, t1;
  411.  
  412.         x = Machine->uixmin + id * Machine->uifontwidth * 16 + 1;
  413.         y = Machine->uiymin + Machine->uiheight - 9;
  414.         n = (w->playpos * 4 / w->smpfreq) & 3;
  415.         t0 = w->playpos / w->smpfreq;
  416.         t1 = w->samples / w->smpfreq;
  417.         sprintf(buf, "%c%c %2d:%02d [%2d:%02d]", n*2+2,n*2+3, t0/60,t0%60, t1/60,t1%60);
  418.         ui_text(buf, x, y);
  419.         tapepos = w->playpos;
  420.     }
  421. }
  422.  
  423.  
  424. static void wave_sound_update(int id, INT16 *buffer, int length)
  425. {
  426.     struct wave_file *w = &wave[id];
  427.     if( !w->timer )
  428.     {
  429.         while( length-- > 0 )
  430.             *buffer++ = 0;
  431.         return;
  432.     }
  433.     /* write mode? */
  434.     if( w->mode )
  435.     {
  436.         if( w->resolution == 16 )
  437.         {
  438.             while( length-- > 0 )
  439.             {
  440.                 w->counter -= w->smpfreq;
  441.                 while( w->counter <= 0 )
  442.                 {
  443.                     w->counter += Machine->sample_rate;
  444.                     *((INT16 *)w->data + w->playpos) = w->record_sample;
  445.                     if( ++w->playpos >= w->samples )
  446.                     {
  447.                         w->samples += w->smpfreq;
  448.                         w->length = w->samples * w->resolution / 8;
  449.                         w->data = realloc(w->data, w->length);
  450.                         if( !w->data )
  451.                         {
  452.                             logerror("WAVE realloc(%d) failed\n", w->length);
  453.                             timer_remove(w->timer);
  454.                             memset(w, 0, sizeof(struct wave_file));
  455.                         }
  456.                     }
  457.                     w->play_sample = w->record_sample;
  458.                 }
  459.                 *buffer++ = w->play_sample;
  460.             }
  461.         }
  462.         else
  463.         {
  464.             while( length-- > 0 )
  465.             {
  466.                 w->counter -= w->smpfreq;
  467.                 while( w->counter <= 0 )
  468.                 {
  469.                     w->counter += Machine->sample_rate;
  470.                     *((INT8 *)w->data + w->playpos) = w->record_sample / 256;
  471.                     if( ++w->playpos >= w->samples )
  472.                     {
  473.                         w->samples += w->smpfreq;
  474.                         w->length = w->samples * w->resolution / 8;
  475.                         w->data = realloc(w->data, w->length);
  476.                         if( !w->data )
  477.                         {
  478.                             logerror("WAVE realloc(%d) failed\n", w->length);
  479.                             timer_remove(w->timer);
  480.                             memset(w, 0, sizeof(struct wave_file));
  481.                         }
  482.                     }
  483.                     w->play_sample = w->record_sample;
  484.                 }
  485.                 *buffer++ = w->play_sample;
  486.             }
  487.         }
  488.     }
  489.     else
  490.     {
  491.         if( w->resolution == 16 )
  492.         {
  493.             while( length-- > 0 )
  494.             {
  495.                 w->counter -= w->smpfreq;
  496.                 while( w->counter <= 0 )
  497.                 {
  498.                     w->counter += Machine->sample_rate;
  499.                     if( ++w->playpos >= w->samples )
  500.                         w->playpos = w->samples - 1;
  501.                     w->play_sample = *((INT16 *)w->data + w->playpos);
  502.                 }
  503.                 *buffer++ = w->play_sample;
  504.             }
  505.         }
  506.         else
  507.         {
  508.             while( length-- > 0 )
  509.             {
  510.                 w->counter -= w->smpfreq;
  511.                 while( w->counter <= 0 )
  512.                 {
  513.                     w->counter += Machine->sample_rate;
  514.                     if( ++w->playpos >= w->samples )
  515.                         w->playpos = w->samples - 1;
  516.                     w->play_sample = 256 * *((INT8 *)w->data + w->playpos);
  517.                 }
  518.                 *buffer++ = w->play_sample;
  519.             }
  520.         }
  521.     }
  522.     if( w->display )
  523.         wave_display(id);
  524. }
  525.  
  526. /*****************************************************************************
  527.  * WaveSound interface
  528.  *****************************************************************************/
  529.  
  530. int wave_sh_start(const struct MachineSound *msound)
  531. {
  532.     int i;
  533.  
  534.     intf = msound->sound_interface;
  535.  
  536.     for( i = 0; i < intf->num; i++ )
  537.     {
  538.         struct wave_file *w = &wave[i];
  539.         char buf[32];
  540.  
  541.         if( intf->num > 1 )
  542.             sprintf(buf, "Cassette #%d", i+1);
  543.         else
  544.             strcpy(buf, "Cassette");
  545.  
  546.         w->channel = stream_init(buf, intf->mixing_level[i], Machine->sample_rate, i, wave_sound_update);
  547.  
  548.         if( w->channel == -1 )
  549.             return 1;
  550.     }
  551.     return 0;
  552. }
  553.  
  554. void wave_sh_stop(void)
  555. {
  556.     int i;
  557.  
  558.     for( i = 0; i < intf->num; i++ )
  559.         wave[i].channel = -1;
  560. }
  561.  
  562. void wave_sh_update(void)
  563. {
  564.     int i;
  565.     for( i = 0; i < intf->num; i++ )
  566.     {
  567.         if( wave[i].channel != -1 )
  568.             stream_update(wave[i].channel, 0);
  569.     }
  570. }
  571.  
  572. /*****************************************************************************
  573.  * IODevice interface functions
  574.  *****************************************************************************/
  575.  
  576. /*
  577.  * return info about a wave device
  578.  */
  579. const void *wave_info(int id, int whatinfo)
  580. {
  581.     return NULL;
  582. }
  583.  
  584. /*
  585.  * You can use this default handler if you don't want
  586.  * to support your own file types with the fill_wave()
  587.  * extension
  588.  */
  589. int wave_init(int id, const char *name)
  590. {
  591.     void *file;
  592.     if( !name || strlen(name) == 0 )
  593.         return INIT_OK;
  594.     file = osd_fopen(Machine->gamedrv->name, name, OSD_FILETYPE_IMAGE_RW, OSD_FOPEN_READ);
  595.     if( file )
  596.     {
  597.         struct wave_args wa = {0,};
  598.         wa.file = file;
  599.         wa.display = 1;
  600.         if( device_open(IO_CASSETTE,id,0,&wa) )
  601.             return INIT_FAILED;
  602.         return INIT_OK;
  603.     }
  604.     return INIT_FAILED;
  605. }
  606.  
  607. void wave_exit(int id)
  608. {
  609.     wave_close(id);
  610. }
  611.  
  612. int wave_status(int id, int newstatus)
  613. {
  614.     struct wave_file *w = &wave[id];
  615.  
  616.     if( !w->file )
  617.         return 0;
  618.  
  619.     if( newstatus != -1 )
  620.     {
  621.         if( newstatus && !w->timer )
  622.         {
  623.             w->timer = timer_set(TIME_NEVER, 0, NULL);
  624.         }
  625.         else
  626.         if( !newstatus && w->timer )
  627.         {
  628.             if( w->timer )
  629.                 w->offset += timer_timeelapsed(w->timer) * w->smpfreq;
  630.             w->timer = NULL;
  631.             bitmap_dirty = 1;
  632.         }
  633.     }
  634.     return w->timer ? 1 : 0;
  635. }
  636.  
  637. int wave_open(int id, int mode, void *args)
  638. {
  639.     struct wave_file *w = &wave[id];
  640.     struct wave_args *wa = args;
  641.     int result;
  642.  
  643.     /* wave already opened? */
  644.     if( w->file )
  645.         wave_close(id);
  646.  
  647.     w->file = wa->file;
  648.     w->mode = mode;
  649.     w->fill_wave = wa->fill_wave;
  650.     w->smpfreq = wa->smpfreq;
  651.     w->display = wa->display;
  652.  
  653.     if( w->mode )
  654.     {
  655.         w->resolution = 16;
  656.         w->samples = w->smpfreq;
  657.         w->length = w->samples * w->resolution / 8;
  658.         w->data = malloc(w->length);
  659.         if( !w->data )
  660.         {
  661.             logerror("WAVE malloc(%d) failed\n", w->length);
  662.             memset(w, 0, sizeof(struct wave_file));
  663.             return WAVE_ERR;
  664.         }
  665.         return INIT_OK;
  666.     }
  667.     else
  668.     {
  669.         result = wave_read(id);
  670.         if( result == WAVE_OK )
  671.         {
  672.             /* return sample frequency in the user supplied structure */
  673.             wa->smpfreq = w->smpfreq;
  674.             w->offset = 0;
  675.             return INIT_OK;
  676.         }
  677.  
  678.         if( result == WAVE_FMT )
  679.         {
  680.             UINT8 *data;
  681.             int bytes, pos, length;
  682.  
  683.             /* User supplied fill_wave function? */
  684.             if( w->fill_wave == NULL )
  685.             {
  686.                 logerror("WAVE no fill_wave callback, failing now\n");
  687.                 return WAVE_ERR;
  688.             }
  689.  
  690.             logerror("WAVE creating wave using fill_wave() callback\n");
  691.  
  692.             /* sanity check: default chunk size is one byte */
  693.             if( wa->chunk_size == 0 )
  694.             {
  695.                 wa->chunk_size = 1;
  696.                 logerror("WAVE chunk_size defaults to %d\n", wa->chunk_size);
  697.             }
  698.             if( wa->smpfreq == 0 )
  699.             {
  700.                 wa->smpfreq = 11025;
  701.                 logerror("WAVE smpfreq defaults to %d\n", w->smpfreq);
  702.             }
  703.  
  704.             /* allocate a buffer for the binary data */
  705.             data = malloc(wa->chunk_size);
  706.             if( !data )
  707.             {
  708.                 free(w->data);
  709.                 /* zap the wave structure */
  710.                 memset(&wave[id], 0, sizeof(struct wave_file));
  711.                 return WAVE_ERR;
  712.             }
  713.  
  714.             /* determine number of samples */
  715.             length =
  716.                 wa->header_samples +
  717.                 ((osd_fsize(w->file) + wa->chunk_size - 1) / wa->chunk_size) * wa->chunk_samples +
  718.                 wa->trailer_samples;
  719.  
  720.             w->smpfreq = wa->smpfreq;
  721.             w->resolution = 16;
  722.             w->samples = length;
  723.             w->length = length * 2;   /* 16 bits per sample */
  724.  
  725.             w->data = malloc(w->length);
  726.             if( !w->data )
  727.             {
  728.                 logerror("WAVE failed to malloc %d bytes\n", w->length);
  729.                 /* zap the wave structure */
  730.                 memset(&wave[id], 0, sizeof(struct wave_file));
  731.                 return WAVE_ERR;
  732.             }
  733.             logerror("WAVE creating max %d:%02d samples (%d) at %d Hz\n", (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60, w->samples, w->smpfreq);
  734.  
  735.             pos = 0;
  736.             /* if there has to be a header */
  737.             if( wa->header_samples > 0 )
  738.             {
  739.                 length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, CODE_HEADER);
  740.                 if( length < 0 )
  741.                 {
  742.                     logerror("WAVE conversion aborted at header\n");
  743.                     free(w->data);
  744.                     /* zap the wave structure */
  745.                     memset(&wave[id], 0, sizeof(struct wave_file));
  746.                     return WAVE_ERR;
  747.                 }
  748.                 logerror("WAVE header %d samples\n", length);
  749.                 pos += length;
  750.             }
  751.  
  752.             /* convert the file data to samples */
  753.             bytes = 0;
  754.             osd_fseek(w->file, 0, SEEK_SET);
  755.             while( pos < w->samples )
  756.             {
  757.                 length = osd_fread(w->file, data, wa->chunk_size);
  758.                 if( length == 0 )
  759.                     break;
  760.                 bytes += length;
  761.                 length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, data);
  762.                 if( length < 0 )
  763.                 {
  764.                     logerror("WAVE conversion aborted at %d bytes (%d samples)\n", bytes, pos);
  765.                     free(w->data);
  766.                     /* zap the wave structure */
  767.                     memset(&wave[id], 0, sizeof(struct wave_file));
  768.                     return WAVE_ERR;
  769.                 }
  770.                 pos += length;
  771.             }
  772.             logerror("WAVE converted %d data bytes to %d samples\n", bytes, pos);
  773.  
  774.             /* if there has to be a trailer */
  775.             if( wa->trailer_samples )
  776.             {
  777.                 if( pos < w->samples )
  778.                 {
  779.                     length = (*w->fill_wave)((INT16 *)w->data + pos, w->samples - pos, CODE_TRAILER);
  780.                     if( length < 0 )
  781.                     {
  782.                         logerror("WAVE conversion aborted at trailer\n");
  783.                         free(w->data);
  784.                         /* zap the wave structure */
  785.                         memset(&wave[id], 0, sizeof(struct wave_file));
  786.                         return WAVE_ERR;
  787.                     }
  788.                     logerror("WAVE trailer %d samples\n", length);
  789.                     pos += length;
  790.                 }
  791.             }
  792.  
  793.             if( pos < w->samples )
  794.             {
  795.                 /* what did the fill_wave() calls really fill into the buffer? */
  796.                 w->samples = pos;
  797.                 w->length = pos * 2;   /* 16 bits per sample */
  798.                 w->data = realloc(w->data, w->length);
  799.                 /* failure in the last step? how sad... */
  800.                 if( !w->data )
  801.                 {
  802.                     logerror("WAVE realloc(%d) failed\n", w->length);
  803.                     /* zap the wave structure */
  804.                     memset(&wave[id], 0, sizeof(struct wave_file));
  805.                     return WAVE_ERR;
  806.                 }
  807.             }
  808.             logerror("WAVE %d samples - %d:%02d\n", w->samples, (w->samples/w->smpfreq)/60, (w->samples/w->smpfreq)%60);
  809.             /* hooray! :-) */
  810.             return INIT_OK;
  811.         }
  812.     }
  813.     return WAVE_ERR;
  814. }
  815.  
  816. void wave_close(int id)
  817. {
  818.     struct wave_file *w = &wave[id];
  819.  
  820.     if( !w->file )
  821.         return;
  822.  
  823.     if( w->timer )
  824.     {
  825.         if( w->channel != -1 )
  826.             stream_update(w->channel, 0);
  827.         w->samples = w->playpos;
  828.         w->length = w->samples * w->resolution / 8;
  829.         timer_remove(w->timer);
  830.         w->timer = NULL;
  831.     }
  832.  
  833.     if( w->mode )
  834.     {
  835.         wave_output(id,0);
  836.         wave_write(id);
  837.         w->mode = 0;
  838.     }
  839.  
  840.     if( w->data )
  841.         free(w->data);
  842.     w->data = NULL;
  843.  
  844.     w->file = NULL;
  845.     w->offset = 0;
  846.     w->playpos = 0;
  847.     w->counter = 0;
  848.     w->smpfreq = 0;
  849.     w->resolution = 0;
  850.     w->samples = 0;
  851.     w->length = 0;
  852. }
  853.  
  854. int wave_seek(int id, int offset, int whence)
  855. {
  856.     struct wave_file *w = &wave[id];
  857.     UINT32 pos = 0;
  858.  
  859.     if( !w->file )
  860.         return pos;
  861.  
  862.     switch( whence )
  863.     {
  864.     case SEEK_SET:
  865.         w->offset = offset;
  866.         break;
  867.     case SEEK_END:
  868.         w->offset = w->samples - 1;
  869.         break;
  870.     case SEEK_CUR:
  871.         if( w->timer )
  872.             pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  873.         w->offset = pos + offset;
  874.         if( w->offset < 0 )
  875.             w->offset = 0;
  876.         if( w->offset >= w->length )
  877.             w->offset = w->length - 1;
  878.     }
  879.     w->playpos = w->offset;
  880.  
  881.     if( w->timer )
  882.     {
  883.         timer_remove(w->timer);
  884.         w->timer = timer_set(TIME_NEVER, 0, NULL);
  885.     }
  886.  
  887.     return w->offset;
  888. }
  889.  
  890. int wave_tell(int id)
  891. {
  892.     struct wave_file *w = &wave[id];
  893.     UINT32 pos = 0;
  894.     if( w->timer )
  895.         pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  896.     if( pos >= w->samples )
  897.         pos = w->samples -1;
  898.     return pos;
  899. }
  900.  
  901. int wave_input(int id)
  902. {
  903.     struct wave_file *w = &wave[id];
  904.     UINT32 pos = 0;
  905.     int level = 0;
  906.  
  907.     if( !w->file )
  908.         return level;
  909.  
  910.     if( w->channel != -1 )
  911.         stream_update(w->channel, 0);
  912.  
  913.     if( w->timer )
  914.     {
  915.         pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  916.         if( pos >= w->samples )
  917.             pos = w->samples - 1;
  918.         w->playpos = pos;
  919.         if( w->resolution == 16 )
  920.             level = *((INT16 *)w->data + pos);
  921.         else
  922.             level = 256 * *((INT8 *)w->data + pos);
  923.     }
  924.     if( w->display )
  925.         wave_display(id);
  926.     return level;
  927. }
  928.  
  929. void wave_output(int id, int data)
  930. {
  931.     struct wave_file *w = &wave[id];
  932.     UINT32 pos = 0;
  933.  
  934.     if( !w->file )
  935.         return;
  936.  
  937.     if( !w->mode )
  938.         return;
  939.  
  940.     if( data == w->record_sample )
  941.         return;
  942.  
  943.     if( w->channel != -1 )
  944.         stream_update(w->channel, 0);
  945.  
  946.     if( w->timer )
  947.     {
  948.         pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  949.         while( pos >= w->samples )
  950.         {
  951.             /* add one second of data */
  952.             w->samples += w->smpfreq;
  953.             w->length = w->samples * w->resolution / 8;
  954.             w->data = realloc(w->data, w->length);
  955.             if( !w->data )
  956.             {
  957.                 logerror("WAVE realloc(%d) failed\n", w->length);
  958.                 memset(w, 0, sizeof(struct wave_file));
  959.                 return;
  960.             }
  961.         }
  962.         while( w->playpos < pos )
  963.         {
  964.             *((INT16 *)w->data + w->playpos) = w->record_sample;
  965.             w->playpos++;
  966.         }
  967.     }
  968.  
  969.     if( w->display )
  970.         wave_display(id);
  971.  
  972.     w->record_sample = data;
  973. }
  974.  
  975. int wave_input_chunk(int id, void *dst, int count)
  976. {
  977.     struct wave_file *w = &wave[id];
  978.     UINT32 pos = 0;
  979.  
  980.     if( !w->file )
  981.         return 0;
  982.  
  983.     if( w->timer )
  984.     {
  985.         pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  986.         if( pos >= w->samples )
  987.             pos = w->samples - 1;
  988.     }
  989.  
  990.     if( pos + count >= w->samples )
  991.         count = w->samples - pos - 1;
  992.  
  993.     if( count > 0 )
  994.     {
  995.         if( w->resolution == 16 )
  996.             memcpy(dst, (INT16 *)w->data + pos, count * sizeof(INT16));
  997.         else
  998.             memcpy(dst, (INT8 *)w->data + pos, count * sizeof(INT8));
  999.     }
  1000.  
  1001.     return count;
  1002. }
  1003.  
  1004. int wave_output_chunk(int id, void *src, int count)
  1005. {
  1006.     struct wave_file *w = &wave[id];
  1007.     UINT32 pos = 0;
  1008.  
  1009.     if( !w->file )
  1010.         return 0;
  1011.  
  1012.     if( w->timer )
  1013.     {
  1014.         pos = w->offset + timer_timeelapsed(w->timer) * w->smpfreq;
  1015.         if( pos >= w->length )
  1016.             pos = w->length - 1;
  1017.     }
  1018.  
  1019.     if( pos + count >= w->length )
  1020.     {
  1021.         /* add space for new data */
  1022.         w->samples += count - pos;
  1023.         w->length = w->samples * w->resolution / 8;
  1024.         w->data = realloc(w->data, w->length);
  1025.         if( !w->data )
  1026.         {
  1027.             logerror("WAVE realloc(%d) failed\n", w->length);
  1028.             memset(w, 0, sizeof(struct wave_file));
  1029.             return 0;
  1030.         }
  1031.     }
  1032.  
  1033.     if( count > 0 )
  1034.     {
  1035.         if( w->resolution == 16 )
  1036.             memcpy((INT16 *)w->data + pos, src, count * sizeof(INT16));
  1037.         else
  1038.             memcpy((INT8 *)w->data + pos, src, count * sizeof(INT8));
  1039.     }
  1040.  
  1041.     return count;
  1042. }
  1043.  
  1044.  
  1045.